/*
 * Funambol is a mobile platform developed by Funambol, Inc.
 * Copyright (C) 2008 Funambol, Inc.
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License version 3 as published by
 * the Free Software Foundation with the addition of the following permission
 * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
 * WORK IN WHICH THE COPYRIGHT IS OWNED BY FUNAMBOL, FUNAMBOL DISCLAIMS THE
 * WARRANTY OF NON INFRINGEMENT  OF THIRD PARTY RIGHTS.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, see http://www.gnu.org/licenses or write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301 USA.
 *
 * You can contact Funambol, Inc. headquarters at 643 Bair Island Road, Suite
 * 305, Redwood City, CA 94063, USA, or at email address info@funambol.com.
 *
 * The interactive user interfaces in modified source and object code versions
 * of this program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU Affero General Public License version 3.
 *
 * In accordance with Section 7(b) of the GNU Affero General Public License
 * version 3, these Appropriate Legal Notices must retain the display of the
 * "Powered by Funambol" logo. If the display of the logo is not reasonably
 * feasible for technical reasons, the Appropriate Legal Notices must display
 * the words "Powered by Funambol".
 */


#import <Foundation/Foundation.h>

#import "UIController.h"
#import "base/Log.h"

#import "FunambolAPI.h"

#import "base/errors.h"
#import "FunambolAPIWrapperImpl.h"
#import "customs.h"

@implementation FunambolAPI

static FunambolAPI*  funAPIInstance = nil;

- (id)init {

    self = [super init];
    return self;
}

+ (FunambolAPI*)getInstance {
    if (funAPIInstance == nil) {
        FunambolAPIWrapperImpl::getInstance()->initializeClient();
        funAPIInstance = [[FunambolAPI alloc] init];
    }
    
    return funAPIInstance;
}

- (void) setSync:(NSString*) syncModes source:(NSString*) source{
    FunambolAPIWrapperImpl::getInstance()->setSync([source UTF8String],[syncModes UTF8String]);
}
- (NSString*)  getSync: (NSString*) source{

    NSString* v = [[NSString alloc] initWithUTF8String: (FunambolAPIWrapperImpl::getInstance()->getSync([source UTF8String]))];
    return v;
}


- (void) setURI:(NSString*) URI syncsourcename:(NSString*) syncsourcename{
    FunambolAPIWrapperImpl::getInstance()->setURI([syncsourcename UTF8String], [URI UTF8String]);
}
- (NSString*)  getURI:(NSString*) syncsourcename{
    NSString* v = [[NSString alloc] initWithUTF8String: (FunambolAPIWrapperImpl::getInstance()->getURI([syncsourcename UTF8String]))];
    return v;
}

- (void) stopSyncContacts{
    //FunambolAPIWrapperImpl apiWrapper;
    //apiWrapper.stopSyncContacts();
}

- (void) stopSyncAndExit{
    FunambolAPIWrapperImpl * apiWrapper = FunambolAPIWrapperImpl::getInstance();
    apiWrapper->stopSyncAndExit();
}

- (void) setRecoverMode:(NSString *) mode
{
    SyncMode syncMode = SYNC_REFRESH_FROM_SERVER;
    if ([mode isEqual:@"recover-from-server"])
    {
        syncMode = SYNC_REFRESH_FROM_SERVER;
    }
    else if ([mode isEqual:@"recover-from-client"])
    {
        syncMode = SYNC_REFRESH_FROM_CLIENT;
    }
    else
    {
        // Should not happen - do nothing
        return;
    }
    FunambolAPIWrapperImpl::getInstance()->setRecoverMode(syncMode);
}

- (void) syncContactsInThread:(id)listener {

    LOG.debug("[SyncThread] starting sync in a thread");
    [NSThread detachNewThreadSelector: @selector(syncContacts:)
                             toTarget:self withObject:listener];
}

- (void) syncCalendarInThread:(id)listener {
    
    LOG.debug("[SyncThread] starting sync in a thread");
    [NSThread detachNewThreadSelector: @selector(syncCalendar:)
                             toTarget:self withObject:listener];
}

- (void) syncNotesInThread:(id)listener {
    
    LOG.debug("[SyncThread] starting sync in a thread");
    [NSThread detachNewThreadSelector: @selector(syncNotes:)
                             toTarget:self withObject:listener];
}

- (void) cleanupInThread:(id) listener contactFlag:(bool)contactFlag 
            calendarFlag:(bool)calendarFlag noteFlag:(bool)noteFlag {
    LOG.debug("[SyncThread] starting sync in a thread");
    contactF = contactFlag;
    calendarF = calendarFlag;
    noteF = noteFlag;
    [NSThread detachNewThreadSelector: @selector(cleanup:)
                             toTarget:self withObject:listener];
}

- (void) syncAllInThread:(id)listener {
    
    LOG.debug("[SyncThread] starting sync in a thread");
    [NSThread detachNewThreadSelector: @selector(syncAll:)
                             toTarget:self withObject:listener];
}

- (void) recoverContactsInThread:(id)listener {

    LOG.debug("[SyncThread] starting sync in a thread");
    [NSThread detachNewThreadSelector: @selector(recoverContacts:)
                                        toTarget:self withObject:listener];
}

- (void) cleanupContactsInThread:(id)listener {

    LOG.debug("[SyncThread] starting sync in a thread");
    [NSThread detachNewThreadSelector: @selector(cleanupContacts:)
                                        toTarget:self withObject:listener];
}

- (int) cleanupContacts:(id)listener {
	//NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];  // create an autorelease pool for this thread

    // Notify the listener that sync about to start
    [listener beginSync:@"addressbook"];
    int res = FunambolAPIWrapperImpl::getInstance()->cleanup("addressbook");
    // Notify the listener that sync is over
    [listener endSync:res sourcename:@"addressbook"];
    
    FunambolAPIWrapperImpl::getInstance()->resetSyncDate("addressbook");
    
    [listener endCleanUp];
    //[pool release];	// actually release any autoreleased objC objects created in this thread
    return res;
}

- (int) recoverContacts:(id)listener {
	//NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];  // create an autorelease pool for this thread
    // Notify the listener that sync about to start
    [listener beginSync:@"addressbook"];
    int res = FunambolAPIWrapperImpl::getInstance()->recoverContacts(listener);
    // Notify the listener that sync is over
    [listener endSync:res sourcename:@"addressbook"];
    
    //[pool release];	// actually release any autoreleased objC objects created in this thread
    return res;
}

- (int) syncContacts:(id)listener {
	//NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];  // create an autorelease pool for this thread

    // Notify the listener that sync about to start
    [listener beginSync:@"addressbook"];
    int res = FunambolAPIWrapperImpl::getInstance()->sync(listener,"addressbook");
    // Notify the listener that sync is over
    [listener endSync:res sourcename:@"addressbook"];
    
    //[pool release];	// actually release any autoreleased objC objects created in this thread
    return res;
}

- (int) syncCalendar:(id)listener {
    //NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];  // create an autorelease pool for this thread
    
    // Notify the listener that sync about to start
    [listener beginSync:@"calendar"];
    int res = FunambolAPIWrapperImpl::getInstance()->sync(listener,"calendar");
    // Notify the listener that sync is over
    [listener endSync:res sourcename:@"calendar"];
    
    //[pool release];	// actually release any autoreleased objC objects created in this thread
    return res;
}

- (int) syncNotes:(id)listener {
   // NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];  // create an autorelease pool for this thread

    // Notify the listener that sync about to start
    [listener beginSync:@"note"];
    int res = FunambolAPIWrapperImpl::getInstance()->sync(listener,"note");
    // Notify the listener that sync is over
    [listener endSync:res sourcename:@"note"];
    
    //[pool release];	// actually release any autoreleased objC objects created in this thread
    return res;
}

- (int) syncAll:(id)listener {
    //NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];  // create an autorelease pool for this thread

    int res = 0;

    if(strcmp(FunambolAPIWrapperImpl::getInstance()->getSync("addressbook"), "none") != 0){
        [listener beginSync:@"addressbook"];
        res = FunambolAPIWrapperImpl::getInstance()->sync(listener,"addressbook");
        [listener endSync:res sourcename:@"addressbook"];
    }
#ifndef FUNAMBOL_APP_STORE
    if(strcmp(FunambolAPIWrapperImpl::getInstance()->getSync("calendar"), "none") != 0){
        [listener beginSync:@"calendar"];
        res = FunambolAPIWrapperImpl::getInstance()->sync(listener,"calendar");
        [listener endSync:res sourcename:@"calendar"];
    }
    if(strcmp(FunambolAPIWrapperImpl::getInstance()->getSync("note"), "none") != 0){
        [listener beginSync:@"note"];
        res = FunambolAPIWrapperImpl::getInstance()->sync(listener,"note");
        [listener endSync:res sourcename:@"note"];
    }
#endif
    
    [listener endSyncAll];
    
    //[pool release];	// actually release any autoreleased objC objects created in this thread
    return res;
}

#ifndef FUNAMBOL_APP_STORE
- (int) cleanup:(id)listener {
    //NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    int res = 0;
    
    if(contactF){
        contactF = false;
        [listener beginSync:@"addressbook"];
        res = FunambolAPIWrapperImpl::getInstance()->cleanup("addressbook");
        [listener endCleanup:res sname:@"addressbook"];
    }
    if(calendarF){
        calendarF = false;
        [listener beginSync:@"calendar"];
        res = FunambolAPIWrapperImpl::getInstance()->cleanup("calendar");
        [listener endCleanup:res sname:@"calendar"];
    }
    if(noteF){
        noteF = false;
        [listener beginSync:@"note"];
        res = FunambolAPIWrapperImpl::getInstance()->cleanup("note");
        [listener endCleanup:res sname:@"note"];
    }
    
    [listener endSyncAll];
    
    //[pool release];	// actually release any autoreleased objC objects created in this thread
    return res;
}
#endif

- (int) getSyncSourceLastSyncDate:(NSString*) sourceName {

    return FunambolAPIWrapperImpl::getInstance()->getLastSyncDate([sourceName UTF8String]);
}

- (void) saveSyncConfig:(NSString*) url
               username:(NSString*) username
               password:(NSString*) password {

      FunambolAPIWrapperImpl::getInstance()->saveSyncConfig([url UTF8String], [username UTF8String],
                              [password UTF8String]);
}

- (void) saveURLConfig:(NSString*) url{
    FunambolAPIWrapperImpl::getInstance()->saveURL([url UTF8String]);
}

- (void) saveUsernameConfig:(NSString*) username{

    FunambolAPIWrapperImpl::getInstance()->saveUsername([username UTF8String]);
}


- (int) getLogLevel{
    
    return FunambolAPIWrapperImpl::getInstance()->getLogLevel();
}

- (void) setLogLevel:(int) loglevel{
    
    FunambolAPIWrapperImpl::getInstance()->setLogLevel(loglevel);
}

- (void) savePasswordConfig:(NSString*) password{
    FunambolAPIWrapperImpl::getInstance()->savePassword([password UTF8String]);
}

- (void) loadSyncConfig:(NSString**) url
               username:(NSString**) username
               password:(NSString**) password {


    

    const char* utf8Username = FunambolAPIWrapperImpl::getInstance()->loadUserNameFromSyncConfig();
    const char* utf8Password = FunambolAPIWrapperImpl::getInstance()->loadPasswordFromSyncConfig();
    const char* utf8Url      = FunambolAPIWrapperImpl::getInstance()->loadUrlFromSyncConfig();

    if (utf8Username){
        *username = [[NSString alloc] initWithUTF8String: utf8Username];
    }else{
        *username = [[NSString alloc] initWithUTF8String: ""];
    }
    if (utf8Password){
        *password = [[NSString alloc] initWithUTF8String: utf8Password];
    }else{
        *password = [[NSString alloc] initWithUTF8String: ""];
    }
    if (utf8Url){
        *url      = [[NSString alloc] initWithUTF8String: utf8Url];
    }else{
        *url      = [[NSString alloc] initWithUTF8String: ""];
    }
}

@end
